package x.ovo.wechat.bot.impl.core;


import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.xml.XmlUtil;
import org.dromara.hutool.http.html.HtmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import x.ovo.wechat.bot.core.Constant;
import x.ovo.wechat.bot.core.Context;
import x.ovo.wechat.bot.core.contact.ContactManager;
import x.ovo.wechat.bot.core.contact.RetrievalType;
import x.ovo.wechat.bot.core.entity.Member;
import x.ovo.wechat.bot.core.enums.MessageType;
import x.ovo.wechat.bot.core.http.WechatApi;
import x.ovo.wechat.bot.core.message.*;
import x.ovo.wechat.bot.core.util.WechatUtil;
import x.ovo.wechat.bot.impl.config.ClientConfig;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 消息工厂
 *
 * @author ovo on 2024/07/18.
 */
@Slf4j(topic = "MessageFactory")
@UtilityClass
public class MessageFactory {

    private final Context ctx = Context.INSTANCE;
    private final ClientConfig config = ClientConfig.get();
    private final WechatApi api = ctx.getApi();
    private final ContactManager manager = ctx.getContactManager();
    private final Map<MessageType, MessageConvertor> map = new HashMap<>() {{
        put(MessageType.TEXT, textMessageConvertor());
        put(MessageType.IMAGE, imageMessageConvertor());
        put(MessageType.VOICE, voiceMessageConvertor());
        put(MessageType.VIDEO, videoMessageConvertor());
        put(MessageType.EMOTICON, emoticonMessageConvertor());
        put(MessageType.SYSTEM, systemMessageConvertor());
        put(MessageType.RECALLED, revolvedMessageConvertor());
        put(MessageType.VERIFY, verifyMessageConvertor());
        put(MessageType.SHARING, sharingMessageConvertor());
    }};

    public Message create(RawMessage rawMessage) {
        MessageType type = MessageType.get(rawMessage.getMsgType());
        Message message = Optional.ofNullable(map.get(type)).orElse(defaultMessageConvertor()).convert(rawMessage);
        fillFields(rawMessage, message, type);
        return message;
    }

    /**
     * 填写字段
     *
     * @param rawMessage 原始消息
     * @param message    消息
     * @param type       类型
     */
    private void fillFields(RawMessage rawMessage, Message message, MessageType type) {
        message.setId(rawMessage.getMsgId());
        message.setRaw(rawMessage);
        message.setType(type);
        message.setFrom(ctx.getContactManager().get(rawMessage.getFromUserName()));
        message.setTo(ctx.getContactManager().get(rawMessage.getToUserName()));
        // 消息正文需要进行html字符串转义后进行格式化，去除空格、unicode控制符和转换emoji
        message.setContent(WechatUtil.format(HtmlUtil.unescape(rawMessage.getContent())));

        // 如果消息是群聊，且消息正文包含群消息分隔符，则需要去除消息分隔符，获取发送消息的群成员信息
        if (rawMessage.isGroup() && rawMessage.getContent().contains(Constant.GROUP_BR)) {
            String[] split = rawMessage.getContent().split(Constant.GROUP_BR);
            // 获取发送消息的群成员信息
            Member member = manager.get(rawMessage.getFromUserName(), split[0], RetrievalType.USER_NAME);
            if (Objects.nonNull(member)) {
                message.setMember(member);
                message.setContent(split.length > 1 ? split[1] : "");
            }
        }
    }

    private MessageConvertor defaultMessageConvertor() {
        return r -> new Message();
    }

    private MessageConvertor textMessageConvertor() {
        return r -> {
            TextMessage message = new TextMessage();
            message.setAtMe(r.getContent().contains("@" + ctx.getSession().getNickName()));
            return message;
        };
    }

    private MessageConvertor imageMessageConvertor() {
        return r -> {
            ImageMessage message = new ImageMessage();
            message.setWidth(r.getImgWidth());
            message.setHeight(r.getImgHeight());
            if (config.getSaveMedia()) {
                String dir = r.isGroup() ? ctx.getContactManager().get(r.getFromUserName()).getNickName() : "Friend";
                File file = FileUtil.file(Constant.Files.IMAGE_DIR, dir, r.getMsgId() + ".jpg");
                byte[] bytes = api.getImage(r.getMsgId());
                message.setBytes(bytes);
                FileUtil.writeBytes(bytes, file);
            }
            return message;
        };
    }

    private MessageConvertor videoMessageConvertor() {
        return r -> {
            VideoMessage message = new VideoMessage();
            message.setLength(r.getPlayLength());
            if (config.getSaveMedia()) {
                String dir = r.isGroup() ? ctx.getContactManager().get(r.getFromUserName()).getNickName() : "Friend";
                File file = FileUtil.file(Constant.Files.VIDEO_DIR, dir, r.getMsgId() + ".mp4");
                byte[] bytes = api.getVideo(r.getMsgId());
                message.setBytes(bytes);
                FileUtil.writeBytes(bytes, file);
            }
            return message;
        };
    }

    private MessageConvertor voiceMessageConvertor() {
        return r -> {
            VoiceMessage message = new VoiceMessage();
            message.setLength(r.getVoiceLength());
            if (config.getSaveMedia()) {
                String dir = r.isGroup() ? ctx.getContactManager().get(r.getFromUserName()).getNickName() : "Friend";
                File file = FileUtil.file(Constant.Files.VOICE_DIR, dir, r.getMsgId() + ".mp3");
                byte[] bytes = api.getVoice(r.getMsgId());
                message.setBytes(bytes);
                FileUtil.writeBytes(bytes, file);
            }
            return message;
        };
    }

    private MessageConvertor emoticonMessageConvertor() {
        return r -> {
            EmoteMessage message = new EmoteMessage();
            message.setMd5(r.getContent());
            return message;
        };
    }

    private MessageConvertor systemMessageConvertor() {
        return r -> new SystemMessage();
    }

    private MessageConvertor revolvedMessageConvertor() {
        return r -> new RevokeMessage();
    }

    private MessageConvertor verifyMessageConvertor() {
        return r -> {
            VerifyMessage message = new VerifyMessage();
            message.setRecommend(r.getRecommendInfo());
            return message;
        };
    }

    private MessageConvertor sharingMessageConvertor() {
        return msg -> {
            SharedMessage message = new SharedMessage();
            String content = HtmlUtil.unescape(msg.getContent()).replaceFirst("@\\w+:<br/>", "").replaceAll("<br/>", "").replaceAll("\t", "");
            if ("该类型暂不支持，请在手机上查看".equals(content)) {
                message.setContent(content);
                message.setShareType(SharedMessage.Type.UNKNOWN);
                message.setTitle("未知类型");
                message.setDescription("未知的分享类型，可能是聊天记录");
                return message;
            }
            Document document = XmlUtil.parseXml(content);
            Element rootElement = XmlUtil.getRootElement(document);
            Element appmsg = XmlUtil.getElement(rootElement, "appmsg");
            SharedMessage.Type type = SharedMessage.Type.get(Integer.parseInt(XmlUtil.elementText(appmsg, "type")));

            // 设置分享消息属性
            message.setShareType(type);
            message.setTitle(XmlUtil.elementText(appmsg, "title"));
            // 微视频分享消息
            if (SharedMessage.Type.MICRO_VIDEO.equals(type)) {
                Element finderFeed = XmlUtil.getElement(appmsg, "finderFeed");
                message.setDescription(XmlUtil.elementText(finderFeed, "desc"));
                return message;
            }
            message.setDescription(XmlUtil.elementText(appmsg, "des").replaceAll("\n", " "));
            message.setUrl(XmlUtil.elementText(appmsg, "url"));
            return message;
        };
    }


    public static void main(String[] args) {
        String data = "&lt;?xml version=\"1.0\"?&gt;<br/>&lt;msg&gt;<br/>\\t&lt;appmsg appid=\"\" sdkver=\"0\"&gt;<br/>\\t\\t&lt;title&gt;当前版本不支持展示该内容，请升级至最新版本。&lt;/title&gt;<br/>\\t\\t&lt;des /&gt;<br/>\\t\\t&lt;username /&gt;<br/>\\t\\t&lt;action&gt;view&lt;/action&gt;<br/>\\t\\t&lt;type&gt;51&lt;/type&gt;<br/>\\t\\t&lt;showtype&gt;0&lt;/showtype&gt;<br/>\\t\\t&lt;content /&gt;<br/>\\t\\t&lt;url&gt;https://support.weixin.qq.com/security/readtemplate?t=w_security_center_website/upgrade&lt;/url&gt;<br/>\\t\\t&lt;lowurl /&gt;<br/>\\t\\t&lt;forwardflag&gt;0&lt;/forwardflag&gt;<br/>\\t\\t&lt;dataurl /&gt;<br/>\\t\\t&lt;lowdataurl /&gt;<br/>\\t\\t&lt;contentattr&gt;0&lt;/contentattr&gt;<br/>\\t\\t&lt;streamvideo&gt;<br/>\\t\\t\\t&lt;streamvideourl /&gt;<br/>\\t\\t\\t&lt;streamvideototaltime&gt;0&lt;/streamvideototaltime&gt;<br/>\\t\\t\\t&lt;streamvideotitle /&gt;<br/>\\t\\t\\t&lt;streamvideowording /&gt;<br/>\\t\\t\\t&lt;streamvideoweburl /&gt;<br/>\\t\\t\\t&lt;streamvideothumburl /&gt;<br/>\\t\\t\\t&lt;streamvideoaduxinfo /&gt;<br/>\\t\\t\\t&lt;streamvideopublishid /&gt;<br/>\\t\\t&lt;/streamvideo&gt;<br/>\\t\\t&lt;canvasPageItem&gt;<br/>\\t\\t\\t&lt;canvasPageXml&gt;&lt;![CDATA[]]&gt;&lt;/canvasPageXml&gt;<br/>\\t\\t&lt;/canvasPageItem&gt;<br/>\\t\\t&lt;appattach&gt;<br/>\\t\\t\\t&lt;totallen&gt;0&lt;/totallen&gt;<br/>\\t\\t\\t&lt;attachid /&gt;<br/>\\t\\t\\t&lt;cdnattachurl /&gt;<br/>\\t\\t\\t&lt;emoticonmd5 /&gt;<br/>\\t\\t\\t&lt;aeskey /&gt;<br/>\\t\\t\\t&lt;fileext /&gt;<br/>\\t\\t\\t&lt;islargefilemsg&gt;0&lt;/islargefilemsg&gt;<br/>\\t\\t&lt;/appattach&gt;<br/>\\t\\t&lt;extinfo /&gt;<br/>\\t\\t&lt;androidsource&gt;0&lt;/androidsource&gt;<br/>\\t\\t&lt;thumburl /&gt;<br/>\\t\\t&lt;mediatagname /&gt;<br/>\\t\\t&lt;messageaction&gt;&lt;![CDATA[]]&gt;&lt;/messageaction&gt;<br/>\\t\\t&lt;messageext&gt;&lt;![CDATA[]]&gt;&lt;/messageext&gt;<br/>\\t\\t&lt;emoticongift&gt;<br/>\\t\\t\\t&lt;packageflag&gt;0&lt;/packageflag&gt;<br/>\\t\\t\\t&lt;packageid /&gt;<br/>\\t\\t&lt;/emoticongift&gt;<br/>\\t\\t&lt;emoticonshared&gt;<br/>\\t\\t\\t&lt;packageflag&gt;0&lt;/packageflag&gt;<br/>\\t\\t\\t&lt;packageid /&gt;<br/>\\t\\t&lt;/emoticonshared&gt;<br/>\\t\\t&lt;designershared&gt;<br/>\\t\\t\\t&lt;designeruin&gt;0&lt;/designeruin&gt;<br/>\\t\\t\\t&lt;designername&gt;null&lt;/designername&gt;<br/>\\t\\t\\t&lt;designerrediretcturl&gt;&lt;![CDATA[null]]&gt;&lt;/designerrediretcturl&gt;<br/>\\t\\t&lt;/designershared&gt;<br/>\\t\\t&lt;emotionpageshared&gt;<br/>\\t\\t\\t&lt;tid&gt;0&lt;/tid&gt;<br/>\\t\\t\\t&lt;title&gt;null&lt;/title&gt;<br/>\\t\\t\\t&lt;desc&gt;null&lt;/desc&gt;<br/>\\t\\t\\t&lt;iconUrl&gt;&lt;![CDATA[null]]&gt;&lt;/iconUrl&gt;<br/>\\t\\t\\t&lt;secondUrl&gt;null&lt;/secondUrl&gt;<br/>\\t\\t\\t&lt;pageType&gt;0&lt;/pageType&gt;<br/>\\t\\t\\t&lt;setKey&gt;null&lt;/setKey&gt;<br/>\\t\\t&lt;/emotionpageshared&gt;<br/>\\t\\t&lt;webviewshared&gt;<br/>\\t\\t\\t&lt;shareUrlOriginal /&gt;<br/>\\t\\t\\t&lt;shareUrlOpen /&gt;<br/>\\t\\t\\t&lt;jsAppId /&gt;<br/>\\t\\t\\t&lt;publisherId /&gt;<br/>\\t\\t\\t&lt;publisherReqId /&gt;<br/>\\t\\t&lt;/webviewshared&gt;<br/>\\t\\t&lt;template_id /&gt;<br/>\\t\\t&lt;md5 /&gt;<br/>\\t\\t&lt;websearch&gt;<br/>\\t\\t\\t&lt;rec_category&gt;0&lt;/rec_category&gt;<br/>\\t\\t\\t&lt;channelId&gt;0&lt;/channelId&gt;<br/>\\t\\t&lt;/websearch&gt;<br/>\\t\\t&lt;weappinfo&gt;<br/>\\t\\t\\t&lt;username /&gt;<br/>\\t\\t\\t&lt;appid /&gt;<br/>\\t\\t\\t&lt;appservicetype&gt;0&lt;/appservicetype&gt;<br/>\\t\\t\\t&lt;secflagforsinglepagemode&gt;0&lt;/secflagforsinglepagemode&gt;<br/>\\t\\t\\t&lt;videopageinfo&gt;<br/>\\t\\t\\t\\t&lt;thumbwidth&gt;0&lt;/thumbwidth&gt;<br/>\\t\\t\\t\\t&lt;thumbheight&gt;0&lt;/thumbheight&gt;<br/>\\t\\t\\t\\t&lt;fromopensdk&gt;0&lt;/fromopensdk&gt;<br/>\\t\\t\\t&lt;/videopageinfo&gt;<br/>\\t\\t&lt;/weappinfo&gt;<br/>\\t\\t&lt;statextstr /&gt;<br/>\\t\\t&lt;musicShareItem&gt;<br/>\\t\\t\\t&lt;musicDuration&gt;0&lt;/musicDuration&gt;<br/>\\t\\t&lt;/musicShareItem&gt;<br/>\\t\\t&lt;finderFeed&gt;<br/>\\t\\t\\t&lt;objectId&gt;14467000217732061648&lt;/objectId&gt;<br/>\\t\\t\\t&lt;objectNonceId&gt;15512058380759466092_4_20_13_1_1724641748893549&lt;/objectNonceId&gt;<br/>\\t\\t\\t&lt;feedType&gt;4&lt;/feedType&gt;<br/>\\t\\t\\t&lt;nickname&gt;娱乐大热搜&lt;/nickname&gt;<br/>\\t\\t\\t&lt;username&gt;v2_060000231003b20faec8c6e08810cbd1ce01ee3cb077c1249ad3e8db7f660c1f226ae1159f3c@finder&lt;/username&gt;<br/>\\t\\t\\t&lt;avatar&gt;&lt;![CDATA[https://wx.qlogo.cn/finderhead/ver_1/2Phwj5UUI2RHJpuZYfgB0JFia7NadvwYicgs7gWmzKQXMxibZMiaPck0zpYe7xTWRKDZwrD6aGZ9pH5icFYiam1GQxr9HEXbxVXCWPLibgqbH2Re1mAGMV5d4R8EB69nNdibD2Sh/0]]&gt;&lt;/avatar&gt;<br/>\\t\\t\\t&lt;desc&gt;这位姑·····叔真是心灵手巧#万万想不到 #大叔 #大神 #手工&lt;/desc&gt;<br/>\\t\\t\\t&lt;mediaCount&gt;1&lt;/mediaCount&gt;<br/>\\t\\t\\t&lt;localId&gt;0&lt;/localId&gt;<br/>\\t\\t\\t&lt;authIconType&gt;0&lt;/authIconType&gt;<br/>\\t\\t\\t&lt;authIconUrl&gt;&lt;![CDATA[]]&gt;&lt;/authIconUrl&gt;<br/>\\t\\t\\t&lt;mediaList&gt;<br/>\\t\\t\\t\\t&lt;media&gt;<br/>\\t\\t\\t\\t\\t&lt;mediaType&gt;4&lt;/mediaType&gt;<br/>\\t\\t\\t\\t\\t&lt;url&gt;&lt;![CDATA[http://wxapp.tc.qq.com/251/20302/stodownload?encfilekey=Cvvj5Ix3eez3Y79SxtvVL0L7CkPM6dFibFeI6caGYwFGwA1DRftP2DDplwCDm4qeqsSzdMFBTVylh6o9Ml4E5KvpFuz5vnelCRnduPDGJrdQNoGoJUtfUx3lCamicfEMibGKfR7bqJoy0Pj5bibRric5icwQ&amp;dotrans=0&amp;hy=SH&amp;idx=1&amp;m=a0833c2adec35244c425828912b932aa&amp;uzid=2&amp;token=o3K9JoTic9IhpSIpTlG60MUDMrLJ7TsxzIGl0A7JPeibwpQe0BQARYDHspAfHVBeqQQuIfNB9yyKJIpmN0ic6ibdiaewtkljOF2aoKL6aIV5FYu75f1ANaJn94w&amp;ctsc=20&amp;extg=108b200&amp;svrbypass=AAuL%2FQsFAAABAAAAAADSjLRKNGT4Z5aT1%2FHLZhAAAADnaHZTnGbFfAj9RgZXfw6V5eQAfoqS6bc3QU5lA3nIAfLzLEZHp2P3G9wzHwob%2FS7mHJvL8eJD9g%3D%3D&amp;svrnonce=1724641751]]&gt;&lt;/url&gt;<br/>\\t\\t\\t\\t\\t&lt;thumbUrl&gt;&lt;![CDATA[http://wxapp.tc.qq.com/251/20304/stodownload?encfilekey=oibeqyX228riaCwo9STVsGLPj9UYCicgttv9qnhPibLmUFK6KQoIay9TQDHTjggAFLibMPLHQkvPczQPWKdoAx33TPqXibwHN5XHq0YTOR2fRb2VMQ3qwN1iaiaNXHtWeVeQMibGafo6iaiaTmV3Gg&amp;bizid=1023&amp;dotrans=0&amp;hy=SH&amp;idx=1&amp;m=986efe4ffe7fa2c6b18d9d5c9651c322&amp;uzid=2&amp;token=oA9SZ4icv8Itxib2MhRju2nvocqDmlCnt41QMWun129GpfecibrliayHjd95qc35FaJCHnUib7A0UsOCMX7SEzkHPoiczuoDgqumO4Rn8Zc3Vymv4&amp;ctsc=2-20]]&gt;&lt;/thumbUrl&gt;<br/>\\t\\t\\t\\t\\t&lt;coverUrl&gt;&lt;![CDATA[http://wxapp.tc.qq.com/251/20304/stodownload?encfilekey=oibeqyX228riaCwo9STVsGLPj9UYCicgttv9qnhPibLmUFK6KQoIay9TQDHTjggAFLibMPLHQkvPczQPWKdoAx33TPqXibwHN5XHq0YTOR2fRb2VMQ3qwN1iaiaNXHtWeVeQMibGafo6iaiaTmV3Gg&amp;bizid=1023&amp;dotrans=0&amp;hy=SH&amp;idx=1&amp;m=986efe4ffe7fa2c6b18d9d5c9651c322&amp;uzid=2&amp;token=oA9SZ4icv8Itxib2MhRju2nvocqDmlCnt41QMWun129GpfecibrliayHjd95qc35FaJCHnUib7A0UsOCMX7SEzkHPoiczuoDgqumO4Rn8Zc3Vymv4&amp;ctsc=2-20]]&gt;&lt;/coverUrl&gt;<br/>\\t\\t\\t\\t\\t&lt;fullCoverUrl&gt;&lt;![CDATA[]]&gt;&lt;/fullCoverUrl&gt;<br/>\\t\\t\\t\\t\\t&lt;fullClipInset&gt;&lt;![CDATA[[0.0,0.0,0.0,0.0]]]&gt;&lt;/fullClipInset&gt;<br/>\\t\\t\\t\\t\\t&lt;width&gt;1088.0&lt;/width&gt;<br/>\\t\\t\\t\\t\\t&lt;height&gt;1920.0&lt;/height&gt;<br/>\\t\\t\\t\\t\\t&lt;videoPlayDuration&gt;23&lt;/videoPlayDuration&gt;<br/>\\t\\t\\t\\t&lt;/media&gt;<br/>\\t\\t\\t&lt;/mediaList&gt;<br/>\\t\\t\\t&lt;megaVideo&gt;<br/>\\t\\t\\t\\t&lt;objectId /&gt;<br/>\\t\\t\\t\\t&lt;objectNonceId /&gt;<br/>\\t\\t\\t&lt;/megaVideo&gt;<br/>\\t\\t\\t&lt;bizUsername /&gt;<br/>\\t\\t\\t&lt;bizNickname /&gt;<br/>\\t\\t\\t&lt;bizAvatar&gt;&lt;![CDATA[]]&gt;&lt;/bizAvatar&gt;<br/>\\t\\t\\t&lt;bizUsernameV2 /&gt;<br/>\\t\\t\\t&lt;bizAuthIconType&gt;0&lt;/bizAuthIconType&gt;<br/>\\t\\t\\t&lt;bizAuthIconUrl&gt;&lt;![CDATA[]]&gt;&lt;/bizAuthIconUrl&gt;<br/>\\t\\t\\t&lt;coverEffectType&gt;0&lt;/coverEffectType&gt;<br/>\\t\\t\\t&lt;coverEffectText&gt;&lt;![CDATA[]]&gt;&lt;/coverEffectText&gt;<br/>\\t\\t\\t&lt;finderForwardSource&gt;&lt;![CDATA[]]&gt;&lt;/finderForwardSource&gt;<br/>\\t\\t\\t&lt;contactJumpInfoStr&gt;&lt;![CDATA[]]&gt;&lt;/contactJumpInfoStr&gt;<br/>\\t\\t\\t&lt;ecSource&gt;&lt;![CDATA[]]&gt;&lt;/ecSource&gt;<br/>\\t\\t\\t&lt;lastGMsgID&gt;&lt;![CDATA[]]&gt;&lt;/lastGMsgID&gt;<br/>\\t\\t\\t&lt;sourceCommentScene&gt;20&lt;/sourceCommentScene&gt;<br/>\\t\\t&lt;/finderFeed&gt;<br/>\\t\\t&lt;finderLiveProductShare&gt;<br/>\\t\\t\\t&lt;finderLiveID&gt;&lt;![CDATA[]]&gt;&lt;/finderLiveID&gt;<br/>\\t\\t\\t&lt;finderUsername&gt;&lt;![CDATA[]]&gt;&lt;/finderUsername&gt;<br/>\\t\\t\\t&lt;finderObjectID&gt;&lt;![CDATA[]]&gt;&lt;/finderObjectID&gt;<br/>\\t\\t\\t&lt;finderNonceID&gt;&lt;![CDATA[]]&gt;&lt;/finderNonceID&gt;<br/>\\t\\t\\t&lt;liveStatus&gt;&lt;![CDATA[]]&gt;&lt;/liveStatus&gt;<br/>\\t\\t\\t&lt;appId&gt;&lt;![CDATA[]]&gt;&lt;/appId&gt;<br/>\\t\\t\\t&lt;pagePath&gt;&lt;![CDATA[]]&gt;&lt;/pagePath&gt;<br/>\\t\\t\\t&lt;productId&gt;&lt;![CDATA[]]&gt;&lt;/productId&gt;<br/>\\t\\t\\t&lt;coverUrl&gt;&lt;![CDATA[]]&gt;&lt;/coverUrl&gt;<br/>\\t\\t\\t&lt;productTitle&gt;&lt;![CDATA[]]&gt;&lt;/productTitle&gt;<br/>\\t\\t\\t&lt;marketPrice&gt;&lt;![CDATA[0]]&gt;&lt;/marketPrice&gt;<br/>\\t\\t\\t&lt;sellingPrice&gt;&lt;![CDATA[0]]&gt;&lt;/sellingPrice&gt;<br/>\\t\\t\\t&lt;platformHeadImg&gt;&lt;![CDATA[]]&gt;&lt;/platformHeadImg&gt;<br/>\\t\\t\\t&lt;platformName&gt;&lt;![CDATA[]]&gt;&lt;/platformName&gt;<br/>\\t\\t\\t&lt;shopWindowId&gt;&lt;![CDATA[]]&gt;&lt;/shopWindowId&gt;<br/>\\t\\t\\t&lt;flashSalePrice&gt;&lt;![CDATA[0]]&gt;&lt;/flashSalePrice&gt;<br/>\\t\\t\\t&lt;flashSaleEndTime&gt;&lt;![CDATA[0]]&gt;&lt;/flashSaleEndTime&gt;<br/>\\t\\t\\t&lt;ecSource&gt;&lt;![CDATA[]]&gt;&lt;/ecSource&gt;<br/>\\t\\t\\t&lt;sellingPriceWording&gt;&lt;![CDATA[]]&gt;&lt;/sellingPriceWording&gt;<br/>\\t\\t\\t&lt;platformIconURL&gt;&lt;![CDATA[]]&gt;&lt;/platformIconURL&gt;<br/>\\t\\t\\t&lt;firstProductTagURL&gt;&lt;![CDATA[]]&gt;&lt;/firstProductTagURL&gt;<br/>\\t\\t\\t&lt;firstProductTagAspectRatioString&gt;&lt;![CDATA[0.0]]&gt;&lt;/firstProductTagAspectRatioString&gt;<br/>\\t\\t\\t&lt;secondProductTagURL&gt;&lt;![CDATA[]]&gt;&lt;/secondProductTagURL&gt;<br/>\\t\\t\\t&lt;secondProductTagAspectRatioString&gt;&lt;![CDATA[0.0]]&gt;&lt;/secondProductTagAspectRatioString&gt;<br/>\\t\\t\\t&lt;firstGuaranteeWording&gt;&lt;![CDATA[]]&gt;&lt;/firstGuaranteeWording&gt;<br/>\\t\\t\\t&lt;secondGuaranteeWording&gt;&lt;![CDATA[]]&gt;&lt;/secondGuaranteeWording&gt;<br/>\\t\\t\\t&lt;thirdGuaranteeWording&gt;&lt;![CDATA[]]&gt;&lt;/thirdGuaranteeWording&gt;<br/>\\t\\t\\t&lt;isPriceBeginShow&gt;false&lt;/isPriceBeginShow&gt;<br/>\\t\\t\\t&lt;lastGMsgID&gt;&lt;![CDATA[]]&gt;&lt;/lastGMsgID&gt;<br/>\\t\\t\\t&lt;promoterKey&gt;&lt;![CDATA[]]&gt;&lt;/promoterKey&gt;<br/>\\t\\t\\t&lt;discountWording&gt;&lt;![CDATA[]]&gt;&lt;/discountWording&gt;<br/>\\t\\t\\t&lt;priceSuffixDescription&gt;&lt;![CDATA[]]&gt;&lt;/priceSuffixDescription&gt;<br/>\\t\\t\\t&lt;showBoxItemStringList /&gt;<br/>\\t\\t&lt;/finderLiveProductShare&gt;<br/>\\t\\t&lt;finderOrder&gt;<br/>\\t\\t\\t&lt;appID&gt;&lt;![CDATA[]]&gt;&lt;/appID&gt;<br/>\\t\\t\\t&lt;orderID&gt;&lt;![CDATA[]]&gt;&lt;/orderID&gt;<br/>\\t\\t\\t&lt;path&gt;&lt;![CDATA[]]&gt;&lt;/path&gt;<br/>\\t\\t\\t&lt;priceWording&gt;&lt;![CDATA[]]&gt;&lt;/priceWording&gt;<br/>\\t\\t\\t&lt;stateWording&gt;&lt;![CDATA[]]&gt;&lt;/stateWording&gt;<br/>\\t\\t\\t&lt;productImageURL&gt;&lt;![CDATA[]]&gt;&lt;/productImageURL&gt;<br/>\\t\\t\\t&lt;products&gt;&lt;![CDATA[]]&gt;&lt;/products&gt;<br/>\\t\\t\\t&lt;productsCount&gt;&lt;![CDATA[0]]&gt;&lt;/productsCount&gt;<br/>\\t\\t&lt;/finderOrder&gt;<br/>\\t\\t&lt;finderShopWindowShare&gt;<br/>\\t\\t\\t&lt;finderUsername&gt;&lt;![CDATA[]]&gt;&lt;/finderUsername&gt;<br/>\\t\\t\\t&lt;avatar&gt;&lt;![CDATA[]]&gt;&lt;/avatar&gt;<br/>\\t\\t\\t&lt;nickname&gt;&lt;![CDATA[]]&gt;&lt;/nickname&gt;<br/>\\t\\t\\t&lt;commodityInStockCount&gt;&lt;![CDATA[]]&gt;&lt;/commodityInStockCount&gt;<br/>\\t\\t\\t&lt;appId&gt;&lt;![CDATA[]]&gt;&lt;/appId&gt;<br/>\\t\\t\\t&lt;path&gt;&lt;![CDATA[]]&gt;&lt;/path&gt;<br/>\\t\\t\\t&lt;appUsername&gt;&lt;![CDATA[]]&gt;&lt;/appUsername&gt;<br/>\\t\\t\\t&lt;query&gt;&lt;![CDATA[]]&gt;&lt;/query&gt;<br/>\\t\\t\\t&lt;liteAppId&gt;&lt;![CDATA[]]&gt;&lt;/liteAppId&gt;<br/>\\t\\t\\t&lt;liteAppPath&gt;&lt;![CDATA[]]&gt;&lt;/liteAppPath&gt;<br/>\\t\\t\\t&lt;liteAppQuery&gt;&lt;![CDATA[]]&gt;&lt;/liteAppQuery&gt;<br/>\\t\\t\\t&lt;platformTagURL&gt;&lt;![CDATA[]]&gt;&lt;/platformTagURL&gt;<br/>\\t\\t\\t&lt;saleWording&gt;&lt;![CDATA[]]&gt;&lt;/saleWording&gt;<br/>\\t\\t\\t&lt;lastGMsgID&gt;&lt;![CDATA[]]&gt;&lt;/lastGMsgID&gt;<br/>\\t\\t\\t&lt;profileTypeWording&gt;&lt;![CDATA[]]&gt;&lt;/profileTypeWording&gt;<br/>\\t\\t\\t&lt;saleWordingExtra&gt;&lt;![CDATA[]]&gt;&lt;/saleWordingExtra&gt;<br/>\\t\\t\\t&lt;reputationInfo&gt;<br/>\\t\\t\\t\\t&lt;hasReputationInfo&gt;0&lt;/hasReputationInfo&gt;<br/>\\t\\t\\t\\t&lt;reputationScore&gt;0&lt;/reputationScore&gt;<br/>\\t\\t\\t\\t&lt;reputationWording /&gt;<br/>\\t\\t\\t\\t&lt;reputationTextColor /&gt;<br/>\\t\\t\\t\\t&lt;reputationLevelWording /&gt;<br/>\\t\\t\\t\\t&lt;reputationBackgroundColor /&gt;<br/>\\t\\t\\t&lt;/reputationInfo&gt;<br/>\\t\\t\\t&lt;productImageURLList /&gt;<br/>\\t\\t&lt;/finderShopWindowShare&gt;<br/>\\t\\t&lt;findernamecard&gt;<br/>\\t\\t\\t&lt;username /&gt;<br/>\\t\\t\\t&lt;avatar&gt;&lt;![CDATA[]]&gt;&lt;/avatar&gt;<br/>\\t\\t\\t&lt;nickname /&gt;<br/>\\t\\t\\t&lt;auth_job /&gt;<br/>\\t\\t\\t&lt;auth_icon&gt;0&lt;/auth_icon&gt;<br/>\\t\\t\\t&lt;auth_icon_url /&gt;<br/>\\t\\t\\t&lt;ecSource&gt;&lt;![CDATA[]]&gt;&lt;/ecSource&gt;<br/>\\t\\t\\t&lt;lastGMsgID&gt;&lt;![CDATA[]]&gt;&lt;/lastGMsgID&gt;<br/>\\t\\t&lt;/findernamecard&gt;<br/>\\t\\t&lt;finderGuarantee&gt;<br/>\\t\\t\\t&lt;scene&gt;&lt;![CDATA[0]]&gt;&lt;/scene&gt;<br/>\\t\\t&lt;/finderGuarantee&gt;<br/>\\t\\t&lt;directshare&gt;0&lt;/directshare&gt;<br/>\\t\\t&lt;gamecenter&gt;<br/>\\t\\t\\t&lt;namecard&gt;<br/>\\t\\t\\t\\t&lt;iconUrl /&gt;<br/>\\t\\t\\t\\t&lt;name /&gt;<br/>\\t\\t\\t\\t&lt;desc /&gt;<br/>\\t\\t\\t\\t&lt;tail /&gt;<br/>\\t\\t\\t\\t&lt;jumpUrl /&gt;<br/>\\t\\t\\t&lt;/namecard&gt;<br/>\\t\\t&lt;/gamecenter&gt;<br/>\\t\\t&lt;patMsg&gt;<br/>\\t\\t\\t&lt;chatUser /&gt;<br/>\\t\\t\\t&lt;records&gt;<br/>\\t\\t\\t\\t&lt;recordNum&gt;0&lt;/recordNum&gt;<br/>\\t\\t\\t&lt;/records&gt;<br/>\\t\\t&lt;/patMsg&gt;<br/>\\t\\t&lt;secretmsg&gt;<br/>\\t\\t\\t&lt;issecretmsg&gt;0&lt;/issecretmsg&gt;<br/>\\t\\t&lt;/secretmsg&gt;<br/>\\t\\t&lt;referfromscene&gt;0&lt;/referfromscene&gt;<br/>\\t\\t&lt;gameshare&gt;<br/>\\t\\t\\t&lt;liteappext&gt;<br/>\\t\\t\\t\\t&lt;liteappbizdata /&gt;<br/>\\t\\t\\t\\t&lt;priority&gt;0&lt;/priority&gt;<br/>\\t\\t\\t&lt;/liteappext&gt;<br/>\\t\\t\\t&lt;appbrandext&gt;<br/>\\t\\t\\t\\t&lt;litegameinfo /&gt;<br/>\\t\\t\\t\\t&lt;priority&gt;-1&lt;/priority&gt;<br/>\\t\\t\\t&lt;/appbrandext&gt;<br/>\\t\\t\\t&lt;gameshareid /&gt;<br/>\\t\\t\\t&lt;sharedata /&gt;<br/>\\t\\t\\t&lt;isvideo&gt;0&lt;/isvideo&gt;<br/>\\t\\t\\t&lt;duration&gt;-1&lt;/duration&gt;<br/>\\t\\t\\t&lt;isexposed&gt;0&lt;/isexposed&gt;<br/>\\t\\t\\t&lt;readtext /&gt;<br/>\\t\\t&lt;/gameshare&gt;<br/>\\t\\t&lt;mpsharetrace&gt;<br/>\\t\\t\\t&lt;hasfinderelement&gt;0&lt;/hasfinderelement&gt;<br/>\\t\\t\\t&lt;lastgmsgid /&gt;<br/>\\t\\t&lt;/mpsharetrace&gt;<br/>\\t\\t&lt;wxgamecard&gt;<br/>\\t\\t\\t&lt;framesetname /&gt;<br/>\\t\\t\\t&lt;mbcarddata /&gt;<br/>\\t\\t\\t&lt;minpkgversion /&gt;<br/>\\t\\t\\t&lt;mbcardheight&gt;0&lt;/mbcardheight&gt;<br/>\\t\\t\\t&lt;isoldversion&gt;0&lt;/isoldversion&gt;<br/>\\t\\t&lt;/wxgamecard&gt;<br/>\\t\\t&lt;liteapp&gt;<br/>\\t\\t\\t&lt;id&gt;null&lt;/id&gt;<br/>\\t\\t\\t&lt;path /&gt;<br/>\\t\\t\\t&lt;query /&gt;<br/>\\t\\t&lt;/liteapp&gt;<br/>\\t&lt;/appmsg&gt;<br/>\\t&lt;fromusername&gt;&lt;/fromusername&gt;<br/>\\t&lt;scene&gt;0&lt;/scene&gt;<br/>\\t&lt;appinfo&gt;<br/>\\t\\t&lt;version&gt;1&lt;/version&gt;<br/>\\t\\t&lt;appname&gt;&lt;/appname&gt;<br/>\\t&lt;/appinfo&gt;<br/>\\t&lt;commenturl&gt;&lt;/commenturl&gt;<br/>&lt;/msg&gt;<br/><br/>";
        data = HtmlUtil.unescape(data).replaceAll("<br/>", "").replaceAll("\t", "");
        Document document = XmlUtil.parseXml(data);
        Element rootElement = XmlUtil.getRootElement(document);
        Element appmsg = XmlUtil.getElement(rootElement, "appmsg");
        Element finderFeed = XmlUtil.getElement(appmsg, "finderFeed");
        XmlUtil.elementText(finderFeed, "desc");
    }

}
